package com.changcheng.project.yuminsi.service.impl;

import com.alibaba.fastjson.JSON;

import com.changcheng.project.yuminsi.commons.RestTemplateCommons;
import com.changcheng.project.yuminsi.domain.OperInfoDomain;
import com.changcheng.project.yuminsi.mapper.CommonMapper;
import com.changcheng.project.yuminsi.domain.AcctInfoDomain;
import com.changcheng.project.yuminsi.domain.CarDomain;
import com.changcheng.project.yuminsi.domain.UserDomain;
import com.changcheng.project.yuminsi.enums.EtcStatus;
import com.changcheng.project.yuminsi.error.BusinessException;
import com.changcheng.project.yuminsi.error.GlobalErrorCode;
import com.changcheng.project.yuminsi.service.ApplyService;
import com.changcheng.project.yuminsi.utils.GenerateSignUtil;
import com.changcheng.project.yuminsi.utils.PBOC;
import com.changcheng.project.yuminsi.vo.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import scj.jl.com.utillibrary.code.CodeTool;


import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @author yuminsi
 * @description
 * @date 2020/8/20 11:14
 * @since
 */
@SuppressWarnings("all")
@Service
public class ApplyServiceImpl implements ApplyService {

    private Logger logger = LoggerFactory.getLogger(ApplyServiceImpl.class);

    @Autowired
    private CommonMapper commonMapper;

    @Autowired
    private RestTemplateCommons restTemplate;

    @Autowired
    private HttpServletRequest request;

    private static String appkey = "9065275281";
    private static String secretkey = "2b673290caa2d9a82f1f7e845c80e4fe";

    /**
     * 3.ETC账户状态查询接口
     *
     * @param acctStatusQueryRequest
     * @return
     */
    @Override
    public BaseOutput getEtcStatus(String vin, String plateNo, String phone) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //拿到请求头数据
        String IMEI = request.getHeader("IMEI");

        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();
        logger.info("路径:  {}", uri);

        //参数
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("vin", vin);
        parameters.put("plateNo", plateNo);
        parameters.put("phone", phone);

        String genSign = GenerateSignUtil.generateSignOfGet(uri, appkey, nonce, timestamp, parameters, secretkey);
        logger.info("Get生成的签名:  {}", genSign);

        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        //1.如果phone和vin以及plateNo都为null,账户不存在
        if (StringUtils.isEmpty(phone) && StringUtils.isEmpty(vin) && StringUtils.isEmpty(plateNo)) {
            throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
        }

        //2.三个都不为null
        AcctInfoDomain acctInfoDomain = null;
        if (StringUtils.isNotEmpty(plateNo) && StringUtils.isNotEmpty(vin) && StringUtils.isNotEmpty(phone)) {
            acctInfoDomain = commonMapper.queryAcctInfoByAll(plateNo, vin, phone);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        //3.如果plateNo和vin不为null
        if (StringUtils.isNotEmpty(plateNo) && StringUtils.isNotEmpty(vin) && StringUtils.isEmpty(phone)) {
            acctInfoDomain = commonMapper.queryAcctInfoByPlateNoAndVin(plateNo, vin);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        //4.如果plateNo和phone不为null
        if (StringUtils.isNotEmpty(plateNo) && StringUtils.isNotEmpty(phone) && StringUtils.isEmpty(vin)) {
            acctInfoDomain = commonMapper.queryAcctInfoByPlateNoAndPhone(plateNo, phone);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        //5.如果phone和vin不为null
        if (StringUtils.isNotEmpty(vin) && StringUtils.isNotEmpty(phone) && StringUtils.isEmpty(plateNo)) {
            acctInfoDomain = commonMapper.queryAcctInfoByVinAndPhone(vin, phone);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        if (StringUtils.isNotEmpty(phone) && StringUtils.isEmpty(plateNo) && StringUtils.isEmpty(vin)) {
            List<AcctInfoDomain> acctInfoDomain1 = new ArrayList<>(commonMapper.queryAcctInfoByPhone(phone));

            List<AcctStatusQueryResponse> list = new ArrayList<>();
            AcctStatusQueryResponse response = null;
            if (!CollectionUtils.isEmpty(acctInfoDomain1)) {
                for (AcctInfoDomain acctInfoDomain2 : acctInfoDomain1) {
                    response = new AcctStatusQueryResponse();
                    response.setAcctId(acctInfoDomain2.getAcctId());
                    response.setVin(acctInfoDomain2.getVin());
                    response.setUsername(acctInfoDomain2.getUsername());
                    response.setObuSn(acctInfoDomain2.getObuSn());
                    response.setIcNumber(acctInfoDomain2.getIcNumber());
                    response.setOrderId(acctInfoDomain2.getOrderId());
//                    EtcStatus etcStatus = EtcStatus.getEtcStatus(acctInfoDomain2.getAccerStatus());
                    response.setStatus(Long.valueOf(acctInfoDomain2.getAccerStatus()));
                    response.setPlateNo(acctInfoDomain2.getPlateNo());
                    response.setBeanId(acctInfoDomain2.getBeanId());
                    response.setPreDataId(Long.valueOf(acctInfoDomain2.getPreDataId()));
                    response.setPhone(acctInfoDomain2.getPhone());
                    response.setEbagNo(acctInfoDomain2.getEbagNo());
                    list.add(response);
                }
                logger.info("list集合：{}", list);
            }
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        //7.如果vin不等于null
        if (StringUtils.isNotEmpty(vin) && StringUtils.isEmpty(plateNo) && StringUtils.isEmpty(phone)) {
            acctInfoDomain = commonMapper.queryAcctInfoByVin(vin);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }

        //8.如果plateNo不等于null
        if (StringUtils.isNotEmpty(plateNo) && StringUtils.isEmpty(phone) && StringUtils.isEmpty(vin)) {
            acctInfoDomain = commonMapper.queryAcctInfoByPlate(plateNo);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
            }
            AcctStatusQueryResponse response = getAcctStatusQueryResponse(acctInfoDomain);
            List<AcctStatusQueryResponse> list = new ArrayList<>();
            list.add(response);
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, list);
        }
        return null;
    }

    public AcctStatusQueryResponse getAcctStatusQueryResponse(AcctInfoDomain acctInfoDomain) {
        AcctStatusQueryResponse response = new AcctStatusQueryResponse();
        response.setAcctId(acctInfoDomain.getAcctId());
        response.setVin(acctInfoDomain.getVin());
        response.setUsername(acctInfoDomain.getUsername());
        response.setObuSn(acctInfoDomain.getObuSn());
        response.setIcNumber(acctInfoDomain.getIcNumber());
        response.setOrderId(acctInfoDomain.getOrderId());
//        EtcStatus etcStatus = EtcStatus.getEtcStatus(acctInfoDomain.getAccerStatus());
        response.setStatus(Long.valueOf(acctInfoDomain.getAccerStatus()));
        response.setPlateNo(acctInfoDomain.getPlateNo());
        response.setBeanId(acctInfoDomain.getBeanId());
        response.setPreDataId(Long.valueOf(acctInfoDomain.getPreDataId()));
        response.setPhone(acctInfoDomain.getPhone());
        response.setEbagNo(acctInfoDomain.getEbagNo());
        return response;
    }

    /**
     * 4.设备认证接口
     *
     * @param deviceAuthRequest
     * @return
     */
    @Override
    public BaseOutput deviceAuth(DeviceAuthRequest deviceAuthRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String deviceAuth = JSON.toJSONString(deviceAuthRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", deviceAuth);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        //账户号
        String acctId = deviceAuthRequest.getAcctId();
        AcctInfoDomain acctInfoDomain = commonMapper.queryAcctInfoByAcctId(acctId);
        if (acctInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
        }
        //随机数
        String nonceStr = deviceAuthRequest.getNonceStr();
        //终端机编号（OBU_SN）
        String deviceSn = deviceAuthRequest.getDeviceSn();
        //秘钥
        String key = acctInfoDomain.getAccerKey();

        //pboc计算mac
        PBOC pboc = new PBOC();
        String mac = pboc.PBOC_3DES_MAC(nonceStr, key);
        DeviceAuthResponse deviceAuthResponse = new DeviceAuthResponse();
        deviceAuthResponse.setMac(mac);
        deviceAuthResponse.setToken(token);
        deviceAuthResponse.setNonceStr(nonceStr);
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, deviceAuthResponse);
    }


    /**
     * 5.用户注册接口
     *
     * @param universalRequest
     * @return
     */
    @Override
    public BaseOutput orderRegister(UniversalRequest universalRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String universal = JSON.toJSONString(universalRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", universal);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String orderId = universalRequest.getOrderId();
        AcctInfoDomain acctInfoDomain = commonMapper.queryAcctInfoByOrderId(orderId);
        if (acctInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.ORDER_NOT_EXIST);
        }
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
    }


    /**
     * 6.车辆验证接口
     *
     * @param universalRequest
     * @return
     */
    @Override
    public BaseOutput vehiVerify(UniversalRequest universalRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String universal = JSON.toJSONString(universalRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", universal);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }


        String orderId = universalRequest.getOrderId();
        AcctInfoDomain acctInfoDomain = commonMapper.queryAcctInfoByOrderId(orderId);
        if (acctInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.ORDER_NOT_EXIST);
        }
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
    }

    /**
     * 7.车辆信息采集接口
     *
     * @param universalRequest
     * @return
     */
    @Override
    public BaseOutput vehiInfoCollect(UniversalRequest universalRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String universal = JSON.toJSONString(universalRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", universal);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }


        String orderId = universalRequest.getOrderId();
        AcctInfoDomain acctInfoDomain = commonMapper.queryAcctInfoByOrderId(orderId);
        if (acctInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.ORDER_NOT_EXIST);
        }
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
    }


    /**
     * 8.卡二发申请接口(写15文件)
     * 国密IC卡更新文件计算MAC:密钥体系（0聚利，1速通）+1字节文件类型（01表示15文件，00表示16文件）
     * +4字节区域代码+8字节卡内部编号+4字节随机数+N字节要更新文件内容+文件偏移+返回IC卡COS指令
     *
     * @param cardIssueRequest
     * @return
     */
    @Override
    public BaseOutput cardIssueApply(CardIssueRequest cardIssueRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");

        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String cardIssue = JSON.toJSONString(cardIssueRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", cardIssue);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

//       if (!genSign.equalsIgnoreCase(sign)) {
//          throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
//        }


        String orderId = cardIssueRequest.getOrderId();
        String cardNo1 = cardIssueRequest.getCardNo();
        String cardNo = cardNo1.substring(cardNo1.length() - 16);
        String random = cardIssueRequest.getRandom();
        //密钥体系（0聚利，1速通）
        Integer keySystem = 0;
        //1字节文件类型
        String fileType = "01";
        //4字节区域代码（北京）
        String areaCode = "B2E2CAD4";
        //文件偏移
        String offset = "20";

        //格式化日期对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        //获取日历对象
        Calendar calendar = Calendar.getInstance();
        //获取当前日期
        Date nowDate = calendar.getTime();
        //启用时间（第21-24字节）
        String signDate = sdf.format(nowDate);
        //到期时间（第25-28字节）
        calendar.setTime(nowDate);
        calendar.add(Calendar.YEAR, 10);
        String expirationDate = sdf.format(calendar.getTime());

        AcctInfoDomain acctInfoDomain;
        CarDomain carDomain = null;
        UserDomain userDomain = null;
        try {
            acctInfoDomain = commonMapper.queryAcctInfoByOrderId(orderId);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.NOT_EXIST);
            }
            carDomain = commonMapper.queryCarInfoByVin(acctInfoDomain.getVin());
            userDomain = commonMapper.queryUserInfoByPhone(acctInfoDomain.getPhone());
        } catch (Exception e) {
            e.printStackTrace();
            BaseOutput.responseData(GlobalErrorCode.FAIL, "");
        }

        //车牌号码（第29-40字节）
        String plateNo = CodeTool.AsciToHexString(carDomain.getPlateNo(), 24);
        //用户类型（第41字节）
        String userType = CodeTool.num2HexStr(Integer.parseInt(userDomain.getUserType()), 1);
        //车牌颜色（第42-43字节）
        String plateColor = CodeTool.num2HexStr(Integer.parseInt(carDomain.getPlateColor()), 2);

        //N字节要更新文件内容
        String fileDate = signDate.concat(expirationDate).concat(plateNo).concat(userType).concat(plateColor);

        logger.info("N字节要更新文件内容 : {}", fileDate);

        StringBuilder sb = new StringBuilder();
        sb.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
        sb.append("<soap12:Body>\n");
        sb.append("<GM_ICC_UPDATEFILE_CALMAC_ALL xmlns=\"http://tempuri.org/\">\n");
        sb.append("<nKeySystemType>" + keySystem + "</nKeySystemType>\n");
        sb.append("<strFileType>" + fileType + "</strFileType>\n");
        sb.append("<strAreaCodeNumber>" + areaCode + "</strAreaCodeNumber>\n");
        sb.append("<strIcSerialNumber>" + cardNo + "</strIcSerialNumber>\n");
        sb.append("<strRandom>" + random + "</strRandom>\n");
        sb.append("<strFileData>" + fileDate + "</strFileData>\n");
        sb.append("<nOffset>" + offset + "</nOffset>\n");
        sb.append("<RCos>" + "" + "</RCos>\n");
        sb.append("</GM_ICC_UPDATEFILE_CALMAC_ALL>\n");
        sb.append("</soap12:Body>\n");
        sb.append("</soap12:Envelope>");

        //获取rCos指令
        CardIssueResponse cardIssueResponse = new CardIssueResponse();
        cardIssueResponse.setApdu(restTemplate.getRcos(sb));
        //销售流水号
        String issueSn = UUID.randomUUID().toString().replace("-", "").substring(0, 10);
        cardIssueResponse.setIssueSn(issueSn);
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, cardIssueResponse);
    }


    /**
     * 9.卡二发结果确认
     *
     * @param issueConfirmRequest
     * @return
     */
    @Override
    public BaseOutput cardIssueConfirm(IssueConfirmRequest issueConfirmRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String issueConfirm = JSON.toJSONString(issueConfirmRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", issueConfirm);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String issueResult = issueConfirmRequest.getIssueResult();
        if ("0".equals(issueResult)) {
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
        }
        throw new BusinessException(GlobalErrorCode.FAIL);
    }


    /**
     * 10.OBU二发写系统信息
     * <p>
     * 国密ESAM更新文件计算MAC:密钥体系（0聚利，1速通）+1字节文件类型(01系统，00车辆)+4字节区域代码+8字节OBU合同序列号
     * +4字节随机数+N字节要更新文件内容+文件偏移+返回ESAM COS指令
     *
     * @param issueSysRequest
     * @return
     */
    @Override
    public BaseOutput obuIssueSys(IssueSysRequest issueSysRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String issueSys = JSON.toJSONString(issueSysRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", issueSys);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String obuId = issueSysRequest.getObuId();
        String orderId = issueSysRequest.getOrderId();
        String random = issueSysRequest.getRandom();

        //密钥体系（0聚利，1速通）
        Integer keySystem = 0;
        //1字节文件类型
        String fileType = "01";
        //4字节区域代码（北京）
        String areaCode = "B2E2CAD4";
        //文件偏移
        String offset = "18";

        //格式化日期对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        //获取日历对象
        Calendar calendar = Calendar.getInstance();
        //获取当前日期
        Date nowDate = calendar.getTime();
        //合同签署日期（第19-22字节）
        String signDate = sdf.format(nowDate);
        //合同过期日期（第23-26字节）
        calendar.setTime(nowDate);
        calendar.add(Calendar.YEAR, 10);
        String expirationDate = sdf.format(calendar.getTime());

        //N字节要更新文件内容:合同签署日期+合同过期日期+拆卸状态
        String fileData = signDate.concat(expirationDate).concat("01");
        logger.info("N字节要更新文件内容 : {}", fileData);

        StringBuilder sb = new StringBuilder();
        sb.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
        sb.append("<soap12:Body>\n");
        sb.append("<GM_ESAM_UPDATEFILE_CALMAC_ALL xmlns=\"http://tempuri.org/\">\n");
        sb.append("<nKeySystemType>" + keySystem + "</nKeySystemType>\n");
        sb.append("<strFileType>" + fileType + "</strFileType>\n");
        sb.append("<strAreaCodeNumber>" + areaCode + "</strAreaCodeNumber>\n");
        sb.append("<strEsamSerialNumber>" + obuId + "</strEsamSerialNumber>\n");
        sb.append("<strRandom>" + random + "</strRandom>\n");
        sb.append("<strFileData>" + fileData + "</strFileData>\n");
        sb.append("<nOffset>" + offset + "</nOffset>\n");
        sb.append("<RCos>" + "" + "</RCos>\n");
        sb.append("</GM_ESAM_UPDATEFILE_CALMAC_ALL>\n");
        sb.append("</soap12:Body>\n");
        sb.append("</soap12:Envelope>");

        //获取cos
        UniversalResponse universalResponse = new UniversalResponse();
        universalResponse.setApdu(restTemplate.getRcos(sb));
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, universalResponse);
    }


    /**
     * 11.OBU二发写车辆信息
     *
     * @param issueVehiRequest
     * @return
     */
    @Override
    public BaseOutput obuIssueVehi(IssueVehiRequest issueVehiRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String issueVehi = JSON.toJSONString(issueVehiRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", issueVehi);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }


        String orderId = issueVehiRequest.getOrderId();
        String obuId = issueVehiRequest.getObuId();
        String random = issueVehiRequest.getRandom();
        //密钥体系（0聚利，1速通）
        Integer keySystem = 0;
        //1字节文件类型(01系统，00车辆)
        String fileType = "00";
        //4字节区域代码（北京）
        String areaCode = "B2E2CAD4";
        //文件偏移
        String offset = "0";

        //N字节要更新文件内容
        AcctInfoDomain acctInfoDomain = null;
        CarDomain carDomain = null;
        try {
            acctInfoDomain = commonMapper.queryAcctInfoByOrderId(orderId);
            if (acctInfoDomain == null) {
                throw new BusinessException(GlobalErrorCode.NOT_EXIST);
            }
            String vin = acctInfoDomain.getVin();
            carDomain = commonMapper.queryCarInfoByVin(vin);
        } catch (Exception e) {
            e.printStackTrace();
            BaseOutput.responseData(GlobalErrorCode.FAIL, "");
        }
        //车牌号（第1-12字节）
        String plateNo = CodeTool.AsciToHexString(carDomain.getPlateNo(), 24);
        //车牌颜色（第13-14字节）
        String plateColor = CodeTool.num2HexStr(Integer.parseInt(carDomain.getPlateColor()), 2);
        //车型（第15节）
        String vehicleType = CodeTool.num2HexStr(Integer.parseInt(carDomain.getVehicleType()), 1);
        //车辆用户类型（第16字节）
        String vehicleUseCharacter = CodeTool.num2HexStr(Integer.parseInt(carDomain.getVehicleUseCharacter()), 1);
        //车辆尺寸（第17-20字节：长2+宽1+高1：单位mm）
        String length = CodeTool.num2HexStr(Long.parseLong(carDomain.getOutsideDimensionsLength()), 2);
        String width = CodeTool.num2HexStr(Long.parseLong(carDomain.getOutsideDimensionsWidth()), 1);
        String height = CodeTool.num2HexStr(Long.parseLong(carDomain.getOutsideDimensionsHeight()), 1);
        //车轮数（第21字节）
        String wheelCount = CodeTool.num2HexStr(Integer.parseInt(carDomain.getWheelCount()), 1);
        //车轴数（第22字节）
        String axleCount = CodeTool.num2HexStr(Integer.parseInt(carDomain.getAxleCount()), 1);
        //轴距（第23-24字节：单位mm）
        String axleDistance = CodeTool.num2HexStr(Long.parseLong(carDomain.getAxleDistance()), 2);
        //车辆载重（货车）/座位数（客车）（第25-27字节：单位kg）
        String approvedCount = CodeTool.num2HexStr(Integer.parseInt(carDomain.getApprovedCount()), 3);
        //车辆特征描述（第28-43字节）
        String vehicleCharacterization = CodeTool.num2HexStr(1, 16);
        //车辆发动机号（第44-59字节）
        String engineNo = CodeTool.num2HexStr(Integer.parseInt(carDomain.getEngineNo()), 16);

        String fileData = plateNo.concat(plateColor).concat(vehicleType).concat(vehicleUseCharacter)
                .concat(length).concat(width).concat(height).concat(wheelCount).concat(axleCount)
                .concat(axleDistance).concat(approvedCount).concat(vehicleCharacterization).concat(engineNo);

        logger.info("N字节要更新文件内容 : {}", fileData);

        StringBuilder sb = new StringBuilder();
        sb.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
        sb.append("<soap12:Body>\n");
        sb.append("<GM_ESAM_UPDATEFILE_CALMAC_ALL xmlns=\"http://tempuri.org/\">\n");
        sb.append("<nKeySystemType>" + keySystem + "</nKeySystemType>\n");
        sb.append("<strFileType>" + fileType + "</strFileType>\n");
        sb.append("<strAreaCodeNumber>" + areaCode + "</strAreaCodeNumber>\n");
        sb.append("<strEsamSerialNumber>" + obuId + "</strEsamSerialNumber>\n");
        sb.append("<strRandom>" + random + "</strRandom>\n");
        sb.append("<strFileData>" + fileData + "</strFileData>\n");
        sb.append("<nOffset>" + offset + "</nOffset>\n");
        sb.append("<RCos>" + "" + "</RCos>\n");
        sb.append("</GM_ESAM_UPDATEFILE_CALMAC_ALL>\n");
        sb.append("</soap12:Body>\n");
        sb.append("</soap12:Envelope>");

        //获取cos
        UniversalResponse universalResponse = new UniversalResponse();
        universalResponse.setApdu(restTemplate.getRcos(sb));
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, universalResponse);
    }


    /**
     * 12.OBU二发通知接口
     *
     * @param issueNoticeRequest
     * @return
     */
    @Override
    public BaseOutput obuIssueNotice(IssueNoticeRequest issueNoticeRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String issueNotice = JSON.toJSONString(issueNoticeRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", issueNotice);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String writeFlag = issueNoticeRequest.getWriteFlag();
        if ("0".equals(writeFlag)) {
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
        }
        throw new BusinessException(GlobalErrorCode.FAIL);
    }


    /**
     * 13.OBU激活接口
     *
     * @param activateRequest
     * @return
     */
    @Override
    public BaseOutput obuActivate(ActivateRequest activateRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String activate = JSON.toJSONString(activateRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", activate);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String acctId = activateRequest.getAcctId();
        String orderId = activateRequest.getOrderId();
        String obuId = activateRequest.getObuId();
        String random = activateRequest.getRandom();

        AcctInfoDomain acctInfoDomain = commonMapper.queryAcctInfoByAcctId(acctId);
        if (acctInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.ACCT_NOT_EXIST);
        }

        //密钥体系（0聚利，1速通）
        Integer keySystem = 0;
        //1字节文件类型
        String fileType = "01";
        //4字节区域代码（北京）
        String areaCode = "B2E2CAD4";
        //文件偏移
        String offset = "26";
        //N字节要更新文件内容
        String fileData = "01";

        StringBuilder sb = new StringBuilder();
        sb.append("<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n");
        sb.append("<soap12:Body>\n");
        sb.append("<GM_ESAM_UPDATEFILE_CALMAC_ALL xmlns=\"http://tempuri.org/\">\n");
        sb.append("<nKeySystemType>" + keySystem + "</nKeySystemType>\n");
        sb.append("<strFileType>" + fileType + "</strFileType>\n");
        sb.append("<strAreaCodeNumber>" + areaCode + "</strAreaCodeNumber>\n");
        sb.append("<strEsamSerialNumber>" + obuId + "</strEsamSerialNumber>\n");
        sb.append("<strRandom>" + random + "</strRandom>\n");
        sb.append("<strFileData>" + fileData + "</strFileData>\n");
        sb.append("<nOffset>" + offset + "</nOffset>\n");
        sb.append("<RCos>" + "" + "</RCos>\n");
        sb.append("</GM_ESAM_UPDATEFILE_CALMAC_ALL>\n");
        sb.append("</soap12:Body>\n");
        sb.append("</soap12:Envelope>");
        logger.info("sb:{}", sb);

        //获取cos
        UniversalResponse universalResponse = new UniversalResponse();
        universalResponse.setApdu(restTemplate.getRcos(sb));
        return BaseOutput.responseData(GlobalErrorCode.SUCCESS, universalResponse);
    }


    /**
     * 14.OBU激活通知接口
     *
     * @param activateNoticeRequest
     * @return
     */
    @Override
    public BaseOutput obuActivateNotice(ActivateNoticeRequest activateNoticeRequest) throws Exception {
        //已经登录放行
        String token = request.getHeader("token");
        OperInfoDomain operInfoDomain = commonMapper.queryOperInfoByToken(token);
        if (operInfoDomain == null) {
            throw new BusinessException(GlobalErrorCode.TOKEN_FAIL);
        }

        //手持机IMEI编号
        String IMEI = request.getHeader("IMEI");
        //签名
        String sign = request.getHeader("bt-auth-sign");
        //header
        String appkey = request.getHeader("bt-auth-appkey");
        String nonce = request.getHeader("bt-auth-nonce");
        String timestamp = request.getHeader("bt-auth-timestamp");

        //url
        String uri = request.getRequestURI();

        //参数
        //对象转json
        String activateNotice = JSON.toJSONString(activateNoticeRequest);
        Map<String, Object> postBody = new HashMap<>();
        postBody.put("json", activateNotice);
        String genSign = GenerateSignUtil.generateSignOfPost(uri, appkey, nonce, timestamp, postBody, secretkey);
        logger.info("POST生成的签名:  {}", genSign);

        //验证签名
        if (!genSign.equalsIgnoreCase(sign)) {
            throw new BusinessException(GlobalErrorCode.SIGN_FAIL);
        }

        String status = activateNoticeRequest.getStatus();
        if ("0".equals(status)) {
            return BaseOutput.responseData(GlobalErrorCode.SUCCESS, null);
        }
        throw new BusinessException(GlobalErrorCode.FAIL);
    }
}
